﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System8ToyMC.Plots;

namespace System8ToyMC
{
	public partial class HistogramArea : UserControl
	{
		public HistogramArea()
		{
			// Required to initialize variables
			InitializeComponent();

            RVarList.VariableAdded += new Action<System8Equations.S8Variable>(RVarList_VariableAdded);
            RVarList.VariablesCleared += new Action(RVarList_VariablesCleared);
		}

        /// <summary>
        /// All the variables were cleared.
        /// </summary>
        void RVarList_VariablesCleared()
        {
            _mgr.RemoveAllVaryingVariables();
            if (_stash != null)
            {
                Calculate(_stash);
            }
        }

        /// <summary>
        /// Called when a new variable is added to the list - we need add it
        /// to the list of things we are watching.
        /// </summary>
        void RVarList_VariableAdded(System8Equations.S8Variable obj)
        {
            _mgr.RemoveVaryingVariable(obj.Path);
            _mgr.AddVaryingVariable(obj);

            if (_stash != null)
            {
                Calculate(_stash);
            }
        }

        private System8Equations.S8Equations _stash = null;

        /// <summary>
        /// Someone wants us to recalc everything! :-)
        /// </summary>
        /// <param name="eqns"></param>
        /// <returns></returns>
        public void Calculate(System8Equations.S8Equations eqns)
        {
            _mgr.Calculate(eqns);
            if (_stash == null)
                _stash = new System8Equations.S8Equations();
            _stash.Copy(eqns);
        }

        /// <summary>
        /// Keeps track of all the histograms we are dealing with
        /// </summary>
        private PlotManager _mgr = new PlotManager();

        /// <summary>
        /// A new histogram is being added for this path. We will create it and put it up there
        /// for display.
        /// </summary>
        public void AddPlot1D(string varPath)
        {
            Histogram h = new Histogram() { Width = 400, Height = 300 };
            AddPlot1D(h, varPath);
        }

        /// <summary>
        /// A new histogram is being added for this path. We will create it and put it up there
        /// for display.
        /// </summary>
        /// <param name="hist"></param>
        /// <param name="varPath"></param>
        public void AddPlot1D(Histogram hist, string varPath)
        {
            ///
            /// We need to figure out if we've alraedy added this. If so, then we should
            /// kick the old one out!
            /// 

            var h = _mgr.FindPlot(varPath);
            if (h != null)
            {
                HPanel.RemovePlot(h);
                _mgr.RemovePlot(varPath);
            }

            ///
            /// Add the new one in!
            /// 

            HPanel.AddPlot(hist);
            _mgr.AddPlot1D(hist, varPath);

            ///
            /// If we have already done a calc, then make sure
            /// to update it to reflect the new plot!
            ///

            if (_stash != null)
            {
                Calculate(_stash);
            }

        }

        /// <summary>
        /// Start a batch update of the plots
        /// </summary>
        public void BeginBatchUpdate()
        {
            _mgr.BeginBatchUpdate();
        }

        /// <summary>
        /// Done with a batch update of lots of plots or lots of changed variables.
        /// </summary>
        public void EndBatchUpdate()
        {
            _mgr.EndBatchUpdate();
        }

        /// <summary>
        /// See if a drop that is arriving is "good" that we can use.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        private bool DragTargetBehavior_DropObjectOK_1(object sender, Behaviors.DragDropDataEventArgs args)
        {
            return args.sourceElement is NamedValue;
        }

        /// <summary>
        /// take the drop info and act upon it.
        /// </summary>
        /// <param name="droppedNV"></param>
        /// <param name="arg2"></param>
        private void DragTargetBehavior_DropObject_1(UIElement droppedNV, UIElement arg2)
        {
            NamedValue val = droppedNV as NamedValue;
            if (val == null)
            {
                throw new InvalidOperationException("Improper drop!");
            }
            AddPlot1D(val.Path);
        }
    }
}